#pragma once

#include <iostream>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"

class Reactor
{
    const static int gnum = 64;

public:
    Reactor()
        : _isrunning(false)
    {
    }
    void AddConnection(int fd, uint32_t events, func_t recver, func_t sender, func_t excepter)
    {
        // 1. 告诉内核关心fd的events事件
        _ep.AddEvents(fd, events);

        // 2. 为fd创建Connection对象
        Connection *conn = new Connection(fd);
        conn->SetEvents(events);
        conn->Register(recver, sender, excepter);
        conn->SetSelf(this);

        // 3.使用unordered_map 对一个个的Connection对象做管理
        _connections[fd] = conn;
    }

    void LoopOnce(int timeout)
    {
        int n = _ep.Wait(revents, gnum, timeout);
        for (int i = 0; i < n; i++)
        {
            uint32_t events = revents[i].events;
            int fd = revents[i].data.fd;
            if (events & EPOLLHUP)
                events |= EPOLLIN | EPOLLOUT;
            if (events & EPOLLERR)
                events |= EPOLLIN | EPOLLOUT;

            if (events & EPOLLIN)
            {
                if (_connections.count(fd) && _connections[fd]->_recver != nullptr)
                    _connections[fd]->_recver(_connections[fd]);
            }
            if (events & EPOLLOUT)
            {
                if (_connections.count(fd) && _connections[fd]->_sender != nullptr)
                    _connections[fd]->_sender(_connections[fd]);
            }
        }
    }
    void Dispatcher()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            LoopOnce(timeout);
        }
        _isrunning = false;
    }
    ~Reactor()
    {
    }

private:
    std::unordered_map<int, Connection *> _connections;
    Epoller _ep;
    struct epoll_event revents[gnum];
    bool _isrunning;
};